<template>
  <div class="container">
    <Breadcrumb :style="{margin: '24px 20px'}">
      <BreadcrumbItem>用户测量数据</BreadcrumbItem>
      <BreadcrumbItem>提取全身照的尺寸数据</BreadcrumbItem>
    </Breadcrumb>
    <Card :style="{padding: '24px', minHeight: '680px', background: '#fff', marginLeft: '20px', minWidth: '1400px'}">
      <Upload
        action="https://jsonplaceholder.typicode.com/posts/"
        class="upload-demo"
        drag
        :before-upload="uploadPic"
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将照片拖到此处，或<em>点击上传照片</em></div>
        <div class="el-upload__tip" slot="tip">只能上传jpg/png文件</div>
      </Upload>
      <div class="input-area">
        <Form :model="form" ref="uForm" label-position="left" label-width="100px">
          <FormItem label="身高（mm）">
            <Input v-model="form.height" type="number" width="200"/>
          </FormItem>
        </Form>
      </div>
      <div class="info-area" v-if="imgUrl">
        <Row :gutter="50"> 
          <Col :span="12">
            <div class="img-wrapper">
              <img :src="imgUrl" alt="" ref="imgToMea">
            </div>
            <div class="testBtn" @click="getPredictData">点击测量人体尺寸</div>
          </Col>
          <Col :span="12">
            <canvas ref="canvas" width="450" height="450"></canvas>
          </Col>
        </Row>
        <div class="title">提取尺寸信息：</div>
        <Row>
          <Col :span="8"><span class="subtitle">臂长：{{measureData.armLength}}</span></Col>
          <Col :span="8"><span class="subtitle">小腿长：{{measureData.legLength}}</span></Col>
          <Col :span="8"><span class="subtitle">肩宽：{{measureData.shoulderWidth}}</span></Col>
        </Row>
        <div class="testBtn" @click="submitMeasureData" v-if="showSubmitBtn">上传图片测量尺寸信息</div>
      </div>
    </Card>
  </div>
</template>
<script>
const bodyPix = require('@tensorflow-models/body-pix');
require("@tensorflow/tfjs-backend-webgl");

export default {
    name: 'picMeasure',
    data () {
      return {
        // imgUrl: 'testPic/people.jpg',
        imgUrl: null,
        picWidth: 400,
        form: {
          height: 0
        },
        measureData: {
          scale: 0,
          armLength: 0,
          legLength: 0,
          shoulderWidth: 0
        },
        showSubmitBtn: false
      }
    },
    methods: {
      getDistance (p1, p2) {
          return ((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2) ** (1 / 2)
      },

      getHeight (data) {
        const width = data.width;
        const height = data.height;
        const sourceArr = data.data;
        // console.log(sourceArr)
        
        let top = 0, bottom = 0;
        
        for (let i = 0; i < height; i++) {
          for (let j = 0; j < width; j++) {
            if (sourceArr[i * width + j] !== -1) {
              top = i;
              break;
            }
          }
          if (top !== 0) break;
        }
        
        for (let i = height - 1; i >= 0; i--) {
          for (let j = 0; j < width; j++) {
            if (sourceArr[i * width + j] !== -1) {
              bottom = i;
              break;
            }
          }
          if (bottom !== 0) break;
        }
        
        // console.log(`top:${top}, bottom:${bottom}`);
        return bottom - top;
      },

      getArmLength (poseData) {
        const keyPoint = poseData.keypoints;
        const leftShoulder = keyPoint[5].position;
        const rightShoulder = keyPoint[6].position;
        const leftElbow = keyPoint[7].position;
        const rightElbow = keyPoint[8].position;
        const leftWrist = keyPoint[9].position;
        const rightWrist = keyPoint[10].position;

        const leftArmLength = this.getDistance(leftShoulder, leftElbow) + this.getDistance(leftElbow, leftWrist);
        const rightArmLength = this.getDistance(rightShoulder, rightElbow) + this.getDistance(rightElbow, rightWrist);
        
        // console.log(leftArmLength, rightArmLength)
        // return (leftArmLength + rightArmLength) / 2;
        return Math.max(leftArmLength, rightArmLength);
      },

      getLegLength (poseData) {
        const keyPoint = poseData.keypoints;
        const leftHip = keyPoint[11].position;
        const rightHip = keyPoint[12].position;
        const leftKnee = keyPoint[13].position;
        const rightKnee = keyPoint[14].position;
        const leftAnkle = keyPoint[15].position;
        const rightAnkle = keyPoint[16].position;

        // 完整腿长
        // const leftLegLength = this.getDistance(leftHip, leftKnee) + this.getDistance(leftKnee, leftAnkle);
        // const rightLegLength = this.getDistance(rightHip, rightKnee) + this.getDistance(rightKnee, rightAnkle);
        // 小腿长
        const leftLegLength = this.getDistance(leftKnee, leftAnkle);
        const rightLegLength = this.getDistance(rightKnee, rightAnkle);

        return (leftLegLength + rightLegLength) / 2;
      },

      getShoulderWidth (data) {
        const keyPoint = data.pose.keypoints;
        const shoulderHeight = Math.floor((keyPoint[5].position.y + keyPoint[6].position.y) / 2);
        const width = data.width;
        const height = data.height;
        const sourceArr = data.data.slice(shoulderHeight * width, (shoulderHeight + 1) * width);
        
        let left = 0, right = 0;
        
        for (let i = 0; i < sourceArr.length; i++) {
          if (sourceArr[i] !== -1) {
            left = i;
            break;
          }
        }
        
        for (let i = sourceArr.length - 1; i >= 0; i--) {
          if (sourceArr[i] !== -1) {
            right = i;
            break;
          }
        }

        return right - left;
      },

      getInfoFromData (data) {
        // if (data.length !== 1) throw new Error('图片没有人或者不止一人');
        // console.log(data)
        const pxDiff = this.getHeight(data);
        // 计算比例尺
        this.measureData.scale = this.form.height / pxDiff;

        this.measureData.armLength = parseInt(this.getArmLength(data.pose) * this.measureData.scale);

        this.measureData.legLength = parseInt(this.getLegLength(data.pose) * this.measureData.scale);

        this.measureData.shoulderWidth = parseInt(this.getShoulderWidth(data) * this.measureData.scale);
      },

      getPredictData () {
        if (this.form.height <= 0) {
          this.$message({
            message: '请输入正确的身高值',
            center: true
          });
          throw new Error('请输入正确的身高值');
        }
        const img = this.$refs.imgToMea;
        async function run (img) {
          const net = await bodyPix.load({
          architecture: 'MobileNetV1',
          outputStride: 8,
          multiplier: 0.75,
          quantBytes: 4
          });
          const segmentation = await net.segmentMultiPersonParts(img, {
            flipHorizontal: false,
            internalResolution: 'high',
            segmentationThreshold: 0.7
          });
          // console.log(partSegmentation)

          // const coloredPartImage = bodyPix.toMask(segmentation);
          // console.log(coloredPartImage)

          // const opacity = 0.7;
          // const flipHorizontal = false;
          // const maskBlurAmount = 0;

          // bodyPix.drawMask(
          // canvas, img, coloredPartImage, opacity, maskBlurAmount,
          // flipHorizontal);
          return segmentation;
        }
        
        let data = null;
        run(img).then(res => {
          data = res;
          console.log(data);
          const img = this.$refs.imgToMea;
          const canvas = this.$refs.canvas;
          const coloredPartImage = bodyPix.toColoredPartMask(data);
          const opacity = 0.7;
          const flipHorizontal = false;
          const maskBlurAmount = 0;
          // Draw the colored part image on top of the original image onto a canvas.
          // The colored part image will be drawn semi-transparent, with an opacity of
          // 0.7, allowing for the original image to be visible under.
          bodyPix.drawMask(
          canvas, img, coloredPartImage, opacity, maskBlurAmount,
          flipHorizontal);
          // 取第0个识别的人体数据
          data = data[0];
          this.getInfoFromData(data);

          this.showSubmitBtn = true;
        }); 
      },

      // 上传图片处理，统一裁剪成200宽的等比例图片，然后再进行测量操作
      uploadPic (file) {
        const self = this;
        const reader=new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function () {
          var imgObj = new Image();
          imgObj.src = this.result;
          imgObj.onload = function () {
            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            var imgWidth = this.width;//上传图片的宽
            var imgHeight = this.height;//上传图片的高
            var scale = imgWidth / imgHeight;
            var maxWidth = self.picWidth,//图片最大宽
                maxHeight = Math.floor(self.picWidth / scale);//图片最大高
            canvas.width = maxWidth;//canvas的宽=图片的宽
            canvas.height = maxHeight;//canvas的高=图片的高
            context.clearRect(0, 0, maxWidth, maxHeight)//清理canvas
            context.drawImage(imgObj, 0, 0, maxWidth, maxHeight)//canvas绘图
            var newUrl = canvas.toDataURL('image',0.92);//canvas导出成为base64
            self.imgUrl = newUrl;
          }
        }
      },

      // 上传图片测量数据
      async submitMeasureData () {
        const res = await this.$http.post('/measure/submit/pic', {
          username: 'ljp',
          measureData: {
            shoulderWidth: this.measureData.shoulderWidth,
            armLength: this.measureData.armLength,
            legLength: this.measureData.legLength
          }
        });
        if (res.code === 200) {
          this.$message({
            message: '数据提交成功',
            center: true,
            type: 'success'
          });
        } else {
          this.$message.error({
            message: '数据提交失败',
            center: true
          });
        }
        // console.log(res);
      }
    }
}
</script>
<style scoped lang="less">
  .container {
    min-width: 1200px;
  }
  .img-wrapper {
    display: inline-block;
    /* max-width: 200px;   */

    img {
      width: 100%;
    }
  }

  .testBtn {
    width: 200px;
    height: 50px;
    background-color: pink;
    text-align: center;
    line-height: 50px;
    cursor: pointer;
    margin-bottom: 30px;
    margin-top: 20px;
  }
  .input-area {
    margin-top: 30px;
  }
</style>